﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using Chisholm.Windows.Live.Library;
using Chisholm.Windows.Live.SSO;
using System.Configuration;
using System.Diagnostics;

namespace Chisholm.Windows.Live.SSOServer
{
    /// <summary>
    /// This implements the SSO Server Engine Service
    /// </summary>
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
    public class SSOServerEngine : ISSOServerEngine
    {
        /// <summary>
        /// This method authenticates the given Windows Live ID against the source server and returns
        /// the Short Lived Token (or an empty string if the user couldn't be authenticated)
        /// </summary>
        /// <param name="windowsliveid">The windows live ID of the user to authenticate</param>
        /// <returns>Either the issued Short Lived Token, or an empty string if an error occurred</returns>
        public string GetSLT(string windowsliveid)
        {
            LiveSLT liveticket = null;

            try
            {
                // First initialise our SLT Ticket
                if (ConfigurationManager.AppSettings["CertificateFile"] != String.Empty)
                {
                    liveticket = new LiveSLT(ConfigurationManager.AppSettings["CertificateFile"],
                        ConfigurationManager.AppSettings["CertificatePassword"],
                        ConfigurationManager.AppSettings["SiteID"],
                        ConfigurationManager.AppSettings["WebProxy"],
                        int.Parse(ConfigurationManager.AppSettings["LoginTimeOut"]));
                }
                else
                {
                    liveticket = new LiveSLT(ConfigurationManager.AppSettings["CertificateThumbPrint"],
                        ConfigurationManager.AppSettings["SiteID"],
                        ConfigurationManager.AppSettings["WebProxy"],
                        int.Parse(ConfigurationManager.AppSettings["LoginTimeOut"]));
                }

                // Then attempt to grab the SLT and return it
                return liveticket.GetSLT(windowsliveid);
            }
            catch (Exception loaderror)
            {
                // An error occurred, so log it and then return an empty SLT
                if (liveticket != null)
                {
                    // Write an error log with the details
                    EventLog.WriteEntry("Windows Live SSO Server",
                    "An error occurred attempt to grab an SLT for user: " + windowsliveid + ". The error returned was: " +
                    Environment.NewLine + liveticket.ExceptionCode + ": " + liveticket.ExceptionMessage + 
                    Environment.NewLine + liveticket.InnerExceptionCode + ": " + liveticket.InnerExceptionMessage, EventLogEntryType.Error);
                }
                else
                    // Write an error log with the exception thrown
                    EventLog.WriteEntry("Windows Live SSO Server",
                    "An error occurred attempt to grab an SLT for user: " + windowsliveid + ". The error returned was: " +
                    Environment.NewLine + loaderror.ToString(), EventLogEntryType.Error);
                return String.Empty;
            }
        }

        /// <summary>
        /// This method authenticates the given Windows Live ID against the source server and then, 
        /// depending on the desired service chosen, returns the redirection URL to that service with
        /// the short lived token and Windows Live ID embedded
        /// </summary>
        /// <param name="windowsliveid">The Windows Live ID of the user to authenticate</param>
        /// <param name="desiredservice">The desired service to access</param>
        /// <returns>The pre-prepared URL ready for redirection</returns>
        public string GetRedirectionURL(string windowsliveid, LiveServiceTypes desiredservice)
        {
            LiveSLT liveticket = null;

            try
            {
                // First initialise our SLT Ticket                
                if (ConfigurationManager.AppSettings["CertificateFile"] != String.Empty)
                {
                    liveticket = new LiveSLT(ConfigurationManager.AppSettings["CertificateFile"],
                        ConfigurationManager.AppSettings["CertificatePassword"],
                        ConfigurationManager.AppSettings["SiteID"],
                        ConfigurationManager.AppSettings["WebProxy"],
                        int.Parse(ConfigurationManager.AppSettings["LoginTimeOut"]));
                }
                else
                {
                    liveticket = new LiveSLT(ConfigurationManager.AppSettings["CertificateThumbPrint"],
                        ConfigurationManager.AppSettings["SiteID"],
                        ConfigurationManager.AppSettings["WebProxy"],
                        int.Parse(ConfigurationManager.AppSettings["LoginTimeOut"]));
                }

                // If no valid SLT was returned, throw an exception
                if (liveticket == null) 
                    throw new ApplicationException("No valid SLT returned from service.");

                // Then return the URL depending on which service was requested
                switch (desiredservice)
                {
                    case LiveServiceTypes.Mail:
                        return liveticket.GetEmailRedirectLocation(windowsliveid);
                    case LiveServiceTypes.SkyDrive:
                        return liveticket.GetSkyDriveRedirectLocation(windowsliveid);
                    case LiveServiceTypes.Calendar:
                        return liveticket.GetCalendarRedirectLocation(windowsliveid);
                    case LiveServiceTypes.Photos:
                        return liveticket.GetPhotoRedirectLocation(windowsliveid);
                }

                // As no supported service was specified througth an exception
                throw new ApplicationException("No valid service specified.");
            }
            catch (Exception loaderror)
            {
                // An error occurred, so log it and then return an empty URL
                if (liveticket != null)
                {
                    // Write an error log with the details
                    EventLog.WriteEntry("Windows Live SSO Server",
                    "An error occurred attempt to grab an SLT for user: " + windowsliveid + ". The error returned was: " +
                    Environment.NewLine + liveticket.ExceptionCode + ": " + liveticket.ExceptionMessage +
                    Environment.NewLine + liveticket.InnerExceptionCode + ": " + liveticket.InnerExceptionMessage, EventLogEntryType.Error);
                }
                else
                    // Write an error log with the exception thrown
                    EventLog.WriteEntry("Windows Live SSO Server",
                    "An error occurred attempt to grab an SLT for user: " + windowsliveid + ". The error returned was: " +
                    Environment.NewLine + loaderror.ToString(), EventLogEntryType.Error);
                return String.Empty;
            }
        }
    }
}
